import {NavBar, InfiniteScroll, Toast, Popup} from 'antd-mobile'
import {useHistory, useParams} from 'react-router-dom'
import {useDispatch} from "react-redux";
import classNames from 'classnames'
import DOMpurify from 'dompurify'
import {useEffect, useRef, useState} from "react";
import ContentLoader from "react-content-loader";
import {useBoolean, useUpdateEffect} from "ahooks";
import hljs from 'highlight.js';
import {throttle} from "lodash";


import Icon from '@/components/Icon'
import CommentItem from './components/CommentItem'
import CommentFooter from './components/CommentFooter'
import {
  followUser,
  getArticleById,
  collectArticle,
  likeArticle,
  getArticleComment,
  getMoreComments, addArticleComment, likeComment
} from "@/store/actions/article";
import useInitState from "@/utils/useInitState";


import 'highlight.js/styles/github.css';
import styles from './index.module.scss'
import CommentInput from "@/pages/Article/components/CommentInput";
import CommentReply from "@/pages/Article/components/CommentReply";

/**
 * 导航栏高度的常量
 */
const NAV_BAR_HEIGTH = 45;

// 弹层结构实现一个动态的切换效果
// 实现切换功能

const Article = () => {
  const [commentReply, setCommentReply] = useState({
    visible: false,
    commentItem: {}
  });
  // 原生hooks
  const wrapperRef = useRef(); // 获取滚动区域的dom
  const authorRef = useRef(null); // 获取作者信息dom
  const commentRef = useRef(null)
  const isShowComment = useRef(false);
  // 内置hooks
  const history = useHistory()
  const dispatch = useDispatch()
  const params = useParams()

  // 自定义hooks
  const [showNavAuthor, {setTrue: setShowNavAuthor, setFalse: setHideNavAuthor}] = useBoolean(false)
  /**
   * 控制评论弹层的标识 ==> 通过ahooks里面的useBoolean实现的
   */
  const [isShowCommentPopup, {setTrue: showCommentPopup, setFalse: hideCommentPopup}] = useBoolean(false)
  const {detail, comment, loading} = useInitState(() => getArticleById(params.artId), 'article');
  const hasMoreComment = comment.end_id !== comment.last_id;
  // 代码块高亮效果处理
  useEffect(() => {
    //处理高亮效果
    if (loading) return
    const dgHtmlDom = document.querySelector('.dg-html')
    const codes = dgHtmlDom.querySelectorAll('pre code')
    hljs.configure({
      // 忽略警告
      ignoreUnescapedHTML: true,
    });
    codes.forEach(el => {
      hljs.highlightElement(el)
    })
  }, [detail, loading])
  /**
   * 顶部Navbar作者信息展示逻辑处理
   */
  useEffect(() => {
    if (loading) return // 如果loading为true，页面没有任何内容，只有一个骨架屏，不需要监听页面滚动信息
    /**
     * 滚动容器的dom结构
     * @type {HTMLElement}
     */
    const wrapperDom = wrapperRef.current
    const authorDom = authorRef.current
    // scroll事件进行节流的处理
    const handleScroll = throttle(() => {
      // 获取正文里面的作者dom距离顶部的距离
      const {bottom} = authorDom.getBoundingClientRect()
      if (bottom < 44) {
        setShowNavAuthor()
      } else {
        setHideNavAuthor()
      }
    }, 500)
    wrapperDom.addEventListener('scroll', handleScroll)
    return () => wrapperDom.removeEventListener('scroll', handleScroll)
  }, [loading])

  const {
    art_id,
    title,
    pubdate,
    aut_id,
    aut_name,
    aut_photo,
    is_followed,
    attitude, // 用户对文章的态度, -1: 无态度，0-不喜欢，1-点赞
    content,
    is_collected,
    read_count,
    comm_count,
    like_count,
  } = detail
  useUpdateEffect(() => {
    dispatch(getArticleComment('a', art_id))
  }, [art_id])
  // 渲染界面的函数或者jsx
  if (loading) {
    return (
      <ContentLoader
        speed={2}
        width={375}
        height={230}
        viewBox="0 0 375 230"
        backgroundColor="#f3f3f3"
        foregroundColor="#ecebeb"
      >
        <rect x="16" y="8" rx="3" ry="3" width="340" height="10"/>
        <rect x="16" y="26" rx="0" ry="0" width="70" height="6"/>
        <rect x="96" y="26" rx="0" ry="0" width="50" height="6"/>
        <rect x="156" y="26" rx="0" ry="0" width="50" height="6"/>
        <circle cx="33" cy="69" r="17"/>
        <rect x="60" y="65" rx="0" ry="0" width="45" height="6"/>
        <rect x="304" y="65" rx="0" ry="0" width="52" height="6"/>
        <rect x="16" y="114" rx="0" ry="0" width="340" height="15"/>
        <rect x="263" y="208" rx="0" ry="0" width="94" height="19"/>
        <rect x="16" y="141" rx="0" ry="0" width="340" height="15"/>
        <rect x="16" y="166" rx="0" ry="0" width="340" height="15"/>
      </ContentLoader>
    )
  }
  const renderArticle = () => {
    // 文章详情
    return (
      <div className="wrapper" ref={wrapperRef}>
        <div className="article-wrapper">
          <div className="header">
            <h1 className="title">{title}</h1>

            <div className="info">
              <span>{pubdate}</span>
              <span>{read_count} 阅读</span>
              <span>{comm_count} 评论</span>
            </div>

            <div className="author" ref={authorRef}>
              <img src="http://geek.itheima.net/images/user_head.jpg" alt=""/>
              <span className="name">黑马先锋</span>
              <span onClick={onFollow} className={classNames('follow', is_followed ? 'followed' : '')}>
                {is_followed ? '已关注' : '关注'}
              </span>
            </div>
          </div>

          <div className="content">
            {/* 渲染内容的区域 */}
            <div
              className="content-html dg-html"
              dangerouslySetInnerHTML={{
                // 会把一些存在风险的标签或者代码过滤掉
                __html: DOMpurify.sanitize(content) // xss 攻击  DOMpurify
              }}
            >
              {/*
                标签正确的解析出来
                到界面上做渲染
              */}
            </div>
            <div className="date">发布文章时间：{pubdate}</div>
          </div>
        </div>

        <div className="comment" ref={commentRef}>
          <div className="comment-header">
            <span>全部评论（{comm_count}）</span>
            <span>{like_count} 点赞</span>
          </div>

          <div className="comment-list">
            {/* 渲染评论数据*/}
            {
              comment.results.map(item => (
                <CommentItem
                  // 当前的评论项
                  onCommentReplyShow={() => onCommentReplyShow(item)}
                  onThumbsUp={() => onThumbsUp(item.com_id, item.is_liking)}
                  key={item.com_id}
                  {...item}
                />
              ))
            }

            <InfiniteScroll
              hasMore={hasMoreComment} // 当前是否还有跟多的数据 lastId === end_id
              loadMore={loadMoreComments}
            />
          </div>
        </div>
      </div>
    )
  }
  const renderCommentPopup = () => {
    return (
      <Popup
        visible={isShowCommentPopup}
        position={'bottom'}
        className={'comment-popup'}
        onMaskClick={hideCommentPopup}
      >
        <CommentInput onAddComment={onAddComment} onClose={hideCommentPopup}/>
      </Popup>
    )
  }
  // 展示回复的弹层组件
  const renderReply = () => {
    return (
      <Popup
        visible={commentReply.visible}
        position={'right'}
        className={'reply-popup'}
      >
        <div className="comment-popup-wrapper">
          <CommentReply
            onThumbsUp={onThumbsUp}
            commentReplyData={commentReply.commentItem}
            onCommentReplyHide={onCommentReplyHide}
            art_id={art_id}
            // 弹层组件可能会复用，所以使用的时候添加一个key，方便区分
            key={commentReply.commentItem.com_id}
          />
        </div>
      </Popup>
    )
  }

  // 跳转评论区域
  const onShowComment = () => {
    console.log('展示评论内容')
    //  获取滚动的容器，让他发生scroll效果
    /**
     * @type {HTMLDivElement}
     */
    const wrapperDom = wrapperRef.current
    //  获取评论部分dom
    const commentDom = commentRef.current
    //  获取评论部分距离可视区域顶部的距离
    const {top: commentTop} = commentDom.getBoundingClientRect()
    if (!isShowComment.current) {
      wrapperDom.scrollTo({
        top: wrapperDom.scrollTop + commentTop - NAV_BAR_HEIGTH,
        behavior: 'smooth'
      })
      isShowComment.current = true
    } else {
      wrapperDom.scrollTo({
        top: 0,
        behavior: 'smooth'
      })
      isShowComment.current = false
    }

  }
  // 关注/取消关注作者
  const onFollow = () => {
    //  提交的时候，需要把作者的id，和是否喜欢的状态提交给服务器
    dispatch(followUser(aut_id, is_followed))
  }

  const onCollected = async () => {
    await dispatch(collectArticle(art_id, is_collected))
    Toast.show(is_collected ? '取消收藏成功' : '收藏成功')
  }

  const onLike = async () => {
    await dispatch(likeArticle(art_id, attitude))
    Toast.show(attitude === 1 ? '取消点赞成功' : '点赞成功')
  }

  const loadMoreComments = async () => {
    await getMoreComments('a', art_id, comment.last_id) // 从什么地方获取偏移量
  }

  const onAddComment = async (content) => {
    // await 提交thunk art_id, content
    await dispatch(addArticleComment(art_id, content))
    Toast.show('发表评论成功')
    //  关闭弹层
    hideCommentPopup()
  }

  // 对评论项的点赞处理
  const onThumbsUp = async (id, is_liking) => {
    console.log(id, is_liking)
    dispatch(likeComment(id, is_liking))
  }

  // 让回复弹层展示的function
  const onCommentReplyShow = commentItem => {
    setCommentReply({
      commentItem, // 记录评论项的目的是为了把当前点击的评论项传递给弹层组件，让弹层组件内部做展示
      visible: true
    })
  }
  // 让回复弹层hide的function
  const onCommentReplyHide = () => {
    setCommentReply({
      ...commentReply,
      visible: false
    })
  }
  return (
    <div className={styles.root}>
      <div className="root-wrapper">
        <NavBar
          onBack={() => history.go(-1)}
          right={
            <span>
              <Icon type="icongengduo"/>
            </span>
          }
        >
          {showNavAuthor && (
            <div className="nav-author">
              <img src="http://geek.itheima.net/images/user_head.jpg" alt=""/>
              <span className="name">黑马先锋</span>
              <span onClick={onFollow} className={classNames('follow', is_followed ? 'followed' : '')}>
                {is_followed ? '已关注' : '关注'}
              </span>
            </div>
          )}
        </NavBar>
        {/* 文章详情和评论 */}
        {renderArticle()}

        {/* 底部评论栏 */}
        <CommentFooter
          total_count={comment.total_count}
          onShowComment={onShowComment}
          onCollected={onCollected}
          is_collect={is_collected}
          attitude={attitude}
          onLike={onLike}
          showCommentPopup={showCommentPopup}
        />
      </div>

      {/* 渲染评论的弹层组件*/}
      {renderCommentPopup()}
      {/*渲染评论回复组件*/}
      {renderReply()}
    </div>
  )
}

export default Article
